import { defineComponent, h, onMounted, PropType, reactive, ref, toRaw, watch } from 'vue';
import { FormItemRule, NDataTable, NForm, NFormItem, NInput } from 'naive-ui';
import { SubListState } from './type';
import Action from './Action.vue';

/**
 * 深拷贝
 * @param prototype 原型
 */
const deepCopy = (prototype: any): typeof prototype => {
  return JSON.parse(JSON.stringify(prototype));
};

export default defineComponent({
  props: {
    /**
     * v-model
     */
    modelValue: {
      type: Array,
      default: () => [],
      required: true,
    },
    /**
     * 列的描述信息
     */
    columns: {
      type: Array as any,
      required: true,
    },
    /**
     * 原型对象（用于new）
     */
    model: {
      type: Object as PropType<{ [key: string]: string }>,
      default: () => Object.assign({}),
    },
    rules: {
      type: Object as PropType<Record<string, Array<FormItemRule>>>,
      default: () => null,
    },
    /**
     * 表格的参数
     */
    tableProps: {
      type: Object as any,
      default: () => ({
        stripe: true,
        border: true,
        size: 'small',
      }),
    },
    /**
     * 添加按钮的标题
     */
    addTitle: {
      type: String as PropType<string>,
      default: () => '+ 添加',
    },
  },
  emits: ['update:modelValue'],
  setup(props, ctx) {
    const sublistState: SubListState<any> = reactive({
      data: props.modelValue ? JSON.parse(JSON.stringify(props.modelValue)) : [],
      editing: false,
      editItem: {},
      editIndex: undefined,
      isNew: false,
      sublistForm: null,
    });

    // SubList表单
    const form = ref();
    onMounted(() => {
      sublistState.sublistForm = form.value;
    });

    //重置状态
    const restoreState = () => {
      sublistState.data = props.modelValue ? JSON.parse(JSON.stringify(props.modelValue)) : [];
      sublistState.editing = false;
      sublistState.editItem = undefined;
      sublistState.editIndex = undefined;
      sublistState.isNew = false;
    };

    watch(
      () => props.modelValue,
      () => {
        restoreState();
      },
    );

    /**
     * 添加数据项并进行编辑
     */
    const addData = (): void => {
      sublistState.data.push(deepCopy(props.model));
      sublistState.editIndex = sublistState.data.length - 1;
      sublistState.editing = true;
      sublistState.editItem = deepCopy(deepCopy(props.model));
      sublistState.isNew = true;
    };

    return {
      ctx,
      sublistState,
      addData,
      form,
    };
  },
  render() {
    const props = this.$props;
    const sublistState = this.sublistState;
    const ctx = this.ctx;
    const tableProps = deepCopy(props.tableProps);

    const formProps: any = {
      size: 'small',
      flexHeight: true,
      inline: true,
      rules: props.rules,
      model: sublistState.editItem,
    };
    props.columns.forEach((column: any) => {
      if (column.type !== 'index') {
        column.render = (row: any, rowIndex: any) => {
          const editComponentBuilder = column.editComponent || getDefaultEditComponent();
          const getRowColumnValue = () => {
            return column.formatter
              ? column.formatter(row, column, row?.[column.key], rowIndex)
              : row?.[column.key];
          };
          return sublistState.editing &&
            column.type !== 'index' &&
            sublistState.editIndex === rowIndex
            ? h(
                editComponentBuilder(
                  {
                    row,
                    column,
                    $index: rowIndex,
                    rowIndex,
                  },
                  sublistState,
                ),
                { ...column },
              )
            : getRowColumnValue();
        };
      } else {
        column.render = (_: any, rowIndex: any) => {
          return rowIndex + 1;
        };
      }
    });

    //编辑
    function actionEdit(row: any, index: any): void {
      sublistState.editIndex = index;
      sublistState.editing = true;
      sublistState.editItem = deepCopy(row);
    }

    //移除
    function actionRemove(index: number): void {
      sublistState?.data?.splice(index, 1);
      ctx.emit('update:modelValue', sublistState.data);
    }

    //确认
    function actionConfirm() {
      sublistState.sublistForm.validate((valid: boolean): void | boolean => {
        if (!valid) {
          if (typeof sublistState?.editIndex === 'number') {
            sublistState.data.splice(
              sublistState?.editIndex,
              1,
              deepCopy(toRaw(sublistState.editItem)),
            );
          }
          // sublistState.editIndex = undefined;
          // sublistState.editItem = undefined;
          sublistState.editing = false;
          ctx.emit('update:modelValue', sublistState.data);
        }
      });
    }

    //取消
    function actionCancel() {
      if (sublistState.isNew) {
        sublistState.data.splice(sublistState.data.length - 1, 1);
      }
      sublistState.editItem = undefined;
      sublistState.editing = false;
      sublistState.editIndex = undefined;
    }

    const actionColumn = {
      title: '操作',
      key: 'action',
      align: 'center',
      width: 90,
      render(row: any, rowIndex: number) {
        return h(Action, {
          state: sublistState,
          rowIndex,
          onConfirm: actionConfirm,
          onCancel: actionCancel,
          onEdit: () => actionEdit(row, rowIndex),
          onRemove: () => actionRemove(rowIndex),
        });
      },
    };
    return (
      <div class="sublist-div">
        {sublistState.data && (
          <NForm ref="form" {...formProps}>
            <NDataTable
              {...tableProps}
              data={sublistState.data}
              columns={[...props.columns, actionColumn]}
            />
          </NForm>
        )}

        {/*新增按钮*/}
        {!sublistState.editing && (
          <n-button
            style={'margin-top: 8px'}
            onClick={() => this.addData()}
            size="small"
            type="primary"
            block
          >
            {props.addTitle}
          </n-button>
        )}
      </div>
    );
  },
});

/**
 * 默认的编辑组件，ElInput 用于编辑或新增
 */
function getDefaultEditComponent(): (scope: any, state: SubListState<any>) => JSX.Element {
  return function (scope, state) {
    return (
      <NFormItem
        size="small"
        // label={scope.column.title}
        path={scope.column.key}
        show-feedback={false}
        show-label={false}
      >
        <NInput
          // label={scope.column.title}
          size="small"
          v-model:value={state.editItem[scope.column.key]}
        />
      </NFormItem>
    );
  };
}
